#include <iostream>
#include <set>

#include "chat_codec.h"
#include "xlcomm/net/tcp_server.h"

using namespace xlcomm;

class ChatServer {
 public:
  ChatServer(net::EventLoop* loop, const net::InetAddress& listen_addr)
      : loop_(loop),
        server_(loop, listen_addr, "ChatServer"),
        codec_(std::bind(&ChatServer::OnStringMessage, this, _1, _2, _3)) {
    server_.set_connect_callback(
        std::bind(&ChatServer::OnConnection, this, _1));
    server_.set_disconnect_callback(
        std::bind(&ChatServer::OnConnection, this, _1));
    server_.set_message_callback(
        std::bind(&ChatCodec::OnMessage, &codec_, _1, _2, _3));
  }

  void Start() { server_.Start(0); }

 private:
  using ConnectionList = std::set<net::TcpConnectionPtr>;

  void OnConnection(const net::TcpConnectionPtr& conn) {
    if (conn->IsConnected()) {
      connections_.insert(conn);
    } else {
      connections_.erase(conn);
    }
  }

  void OnStringMessage(const net::TcpConnectionPtr& conn,
                       const std::string& msg, Timestamp recv_time) {
    std::cout << __FUNCTION__ << " msg:" << msg << std::endl;
    ConnectionList::iterator it;
    for (it = connections_.begin(); it != connections_.end(); it++) {
      codec_.Send(*it, msg);
    }
  }

  net::EventLoop* loop_;
  net::TcpServer server_;
  ConnectionList connections_;
  ChatCodec codec_;
};

int main() {
  net::EventLoop loop;
  ChatServer server(&loop, net::InetAddress(30001));
  server.Start();
  loop.Loop();
  return 0;
}